package org.apache.dubbo.config.spring.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.AliasRegistry;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.beans.Introspector;
import java.util.Iterator;
import java.util.List;

/**
 * @author chenkh
 * @time 2021/8/3 10:35
 */
public abstract class BeanRegistrar {
    private static final Log log = LogFactory.getLog(com.alibaba.spring.util.BeanRegistrar.class);

    public BeanRegistrar() {
    }

    public static boolean registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry, String beanName, Class<?> beanType) {
        boolean registered = false;
        if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
            beanDefinition.setRole(2);
            beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
            registered = true;
            if (log.isInfoEnabled()) {
                log.info("The Infrastructure bean definition [" + beanDefinition + "with name [" + beanName + "] has been registered.");
            }
        }

        return registered;
    }

    public static boolean hasAlias(AliasRegistry registry, String beanName, String alias) {
        return StringUtils.hasText(beanName) && StringUtils.hasText(alias) && ObjectUtils.containsElement(registry.getAliases(beanName), alias);
    }

    public static int registerSpringFactoriesBeans(BeanDefinitionRegistry registry, Class<?>... factoryClasses) {
        int count = 0;
        ClassLoader classLoader = registry.getClass().getClassLoader();

        for(int i = 0; i < factoryClasses.length; ++i) {
            Class<?> factoryClass = factoryClasses[i];
            List<String> factoryImplClassNames = SpringFactoriesLoader.loadFactoryNames(factoryClass, classLoader);
            Iterator var7 = factoryImplClassNames.iterator();

            while(var7.hasNext()) {
                String factoryImplClassName = (String)var7.next();
                Class<?> factoryImplClass = ClassUtils.resolveClassName(factoryImplClassName, classLoader);
                String beanName = Introspector.decapitalize(ClassUtils.getShortName(factoryImplClassName));
                if (registerInfrastructureBean(registry, beanName, factoryImplClass)) {
                    ++count;
                } else if (log.isWarnEnabled()) {
                    log.warn(String.format("The Factory Class bean[%s] has been registered with bean name[%s]", factoryImplClassName, beanName));
                }
            }
        }

        return count;
    }
}
